var cycleArray = function(size) {
  // @visualize global
  let arr = new Array(size).fill(null);
  // @visualize global
  let start = 0;
  // @visualize global
  let end = 0;
  // @visualize global
  // 用来跟踪数组中的元素数量
  let count = 0;

  var getFirst = function() {
      if (isEmpty()) {
          throw new Error("Array is empty");
      }
      return arr[start];
  }

  var getLast = function() {
      if (isEmpty()) {
          throw new Error("Array is empty");
      }
      // 由于 end 是开区间，即指向最后一个元素的下一个位置
      // 所以需要回退一步来获取最后一个元素
      return arr[(end - 1 + size) % size];
  }


  var addFirst = function(val) {
      if (isFull()) {
          throw new Error("Array is full");
      }
      // 循环移动到前一个位置
      start = (start - 1 + size) % size;
      arr[start] = val;
      count++;
  }


  var removeFirst = function() {
      if (isEmpty()) {
          throw new Error("Array is empty");
      }
      arr[start] = null;
      // 循环移动到下一个位置
      start = (start + 1) % size;
      count--;
  }

  var addLast = function(val) {
      if (isFull()) {
          throw new Error("Array is full");
      }
      arr[end] = val;
      // 循环移动到下一个位置
      end = (end + 1) % size;
      count++;
  }

  var removeLast = function() {
      if (isEmpty()) {
          throw new Error("Array is empty");
      }
      // 循环移动到前一个位置
      end = (end - 1 + size) % size;
      arr[end] = null;
      count--;
  }

  var isFull = function() {
      return count === size;
  }

  var isEmpty = function() {
      return count === 0;
  }

  // 返回所有方法供外部调用
  return { addFirst, removeFirst, addLast, removeLast, isFull, isEmpty, getLast, getFirst };
}

// @visualize hide
let arr = cycleArray(6);

arr.addLast(1);
arr.addLast(2);
// [1, 2, _, _, _, _]

arr.addFirst(3);
// [1, 2, _, _, _, 3]

arr.addFirst(4);
// [1, 2, _, _, 4, 3]

arr.addFirst(5);
// [1, 2, _, 5, 4, 3]

arr.removeLast();
// [1, _, _, 5, 4, 3]

arr.removeFirst();
// [1, _, _, _, 4, 3]

let first = arr.getFirst(); // 4
let last = arr.getLast(); // 1

arr.removeLast();
// [_, _, _, _, 4, 3]

arr.removeLast();
// [_, _, _, _, 4, _]